﻿using AutoMapper;
using Furion.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using MySql.EntityFrameworkCore.Extensions;
using XinGuanERP.Db;
using XinGuanERP.Enums.system;
using XinGuanERP.Models.Po.business;
using XinGuanERP.Models.Vo.business;
using XinGuanERP.Services.business.IServices;
using XinGuanERP.Utils;

namespace XinGuanERP.Services.business
{
    public class ProductService : IProductService, ITransient
    {
        private readonly DefaultDbContext _defaultDbContext;
        public ProductService(DefaultDbContext defaultDbContext)
        {
            _defaultDbContext = defaultDbContext;
        }

        public bool AddProduct(ProductVo productVo)
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<ProductVo, Product>()
                    .BeforeMap((src, des) => des.OneCategoryId = src.CategoryId[0])
                    .BeforeMap((src, des) => des.TwoCategoryId = src.CategoryId[1])
                    .BeforeMap((src, des) => des.ThreeCategoryId = src.CategoryId[2])
                    .BeforeMap((src, des) => src.Id = StrUtil.GUID())
                    .AfterMap((src, des) => des.CreateTime = DateTime.Now)
                    .BeforeMap((src, des) => des.CreateUserId = SecurityUtil.FindClaimValue("UserId"))
                    .BeforeMap((src, des) => des.CreateUserName = SecurityUtil.FindClaimValue("UserName"));
            });
            var mapper = config.CreateMapper();
            _defaultDbContext.Products.Add(mapper.Map<Product>(productVo));
            return _defaultDbContext.SaveChanges() > 0;
        }

        public bool UpdateProduct(ProductVo productVo)
        {
            var res = _defaultDbContext.Products.FirstOrDefault(t => t.Id == productVo.Id);
            if (res == null) return false;
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<ProductVo, Product>()
                    .AfterMap((src, des) => des.OneCategoryId = src.CategoryId[0])
                    .AfterMap((src, des) => des.TwoCategoryId = src.CategoryId[1])
                    .AfterMap((src, des) => des.ThreeCategoryId = src.CategoryId[2])
                    .AfterMap((src, des) => des.UpdateTime = DateTime.Now)
                    .BeforeMap((src, des) => des.UpdateUserId = SecurityUtil.FindClaimValue("UserId"))
                    .BeforeMap((src, des) => des.UpdateUserName = SecurityUtil.FindClaimValue("UserName"));
            });
            var mapper = config.CreateMapper();
            mapper.Map(productVo, res);
            _defaultDbContext.Products.Update(res);
            return _defaultDbContext.SaveChanges() > 0;
        }

        public bool DeleteProduct(string id)
        {
            var res = _defaultDbContext.Products.FirstOrDefault(t => t.Id == id);
            if (res == null) return false;
            _defaultDbContext.Products.Remove(res);
            return _defaultDbContext.SaveChanges() > 0;
        }

        public PageResult<ProductVo> GetProductWithPage(ProductVo productVo)
        {
            var page = productVo.page;
            var pageSize = productVo.pageSize;
            var res = new List<Product>();
            var count = 0;
            var sql = _defaultDbContext.Products.OrderBy(t => t.Sort).AsQueryable();
            if (!string.IsNullOrWhiteSpace(productVo.Status) && string.IsNullOrWhiteSpace(productVo.Name))
            {
                res = sql.Where(t =>
                    t.Status == productVo.Status)
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t => t.Status == productVo.Status);
            }
            else if (productVo.CategoryId != null && productVo.CategoryId.Length > 2 && !string.IsNullOrWhiteSpace(productVo.CategoryId[2]))
            {
                productVo.ThreeCategoryId = productVo.CategoryId[2];
                productVo.TwoCategoryId = productVo.CategoryId[1];
                productVo.OneCategoryId = productVo.CategoryId[0];
                res = sql.Where(t =>
                    t.OneCategoryId == productVo.OneCategoryId &&
                    t.TwoCategoryId == productVo.TwoCategoryId &&
                    t.ThreeCategoryId == productVo.ThreeCategoryId)
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t =>
                    t.OneCategoryId == productVo.OneCategoryId &&
                    t.TwoCategoryId == productVo.TwoCategoryId &&
                    t.ThreeCategoryId == productVo.ThreeCategoryId);
            }
            else if (productVo.CategoryId != null && productVo.CategoryId.Length > 1 && !string.IsNullOrWhiteSpace(productVo.CategoryId[1]))
            {
                productVo.TwoCategoryId = productVo.CategoryId[1];
                productVo.OneCategoryId = productVo.CategoryId[0];
                res = sql.Where(t =>
                    t.OneCategoryId == productVo.OneCategoryId &&
                    t.TwoCategoryId == productVo.TwoCategoryId)
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t =>
                    t.OneCategoryId == productVo.OneCategoryId &&
                    t.TwoCategoryId == productVo.TwoCategoryId);
            }
            else if (productVo.CategoryId != null && productVo.CategoryId.Length > 0 && !string.IsNullOrWhiteSpace(productVo.CategoryId[0]))
            {
                productVo.OneCategoryId = productVo.CategoryId[0];
                res = sql.Where(t =>
                    t.OneCategoryId == productVo.OneCategoryId)
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t =>
                    t.OneCategoryId == productVo.OneCategoryId);
            }
            else if (!string.IsNullOrWhiteSpace(productVo.Name) && string.IsNullOrWhiteSpace(productVo.Status))
            {
                res = sql.Where(t => 
                    EF.Functions.Like(t.Name, "%" + productVo.Name + "%"))
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t => EF.Functions.Like(t.Name, "%" + productVo.Name + "%"));
            }
            else if (!string.IsNullOrWhiteSpace(productVo.Name) && !string.IsNullOrWhiteSpace(productVo.Status))
            {
                res = sql.Where(t => 
                        EF.Functions.Like(t.Name, "%" + productVo.Name + "%"))
                    .Where(t =>
                        EF.Functions.Like(t.Status, "%" + productVo.Status + "%"))
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Where(t => EF.Functions.Like(t.Status, "%" + productVo.Status + "%"))
                    .Count(t => EF.Functions.Like(t.Name, "%" + productVo.Name + "%"));
            }
            else
            {
                res = sql.Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count();
            }

            var config = new MapperConfiguration(cfg => cfg.CreateMap<Product, ProductVo>()
                .BeforeMap((src, des) =>
                    des.CategoryId = new[] { src.OneCategoryId, src.TwoCategoryId, src.ThreeCategoryId }));
            
            var mapper = config.CreateMapper();
            return new PageResult<ProductVo>()
            {
                Items = res.Select(item =>
                    {
                        var a = mapper.Map<ProductVo>(item);
                        if (a.CategoryId[0] == null)
                            a.CategoryId = null;
                        return a;
                    }
                ).ToList(),
                Total = count
            };
        }

        public List<ProductVo> GetProductWithList()
        {
            var res = new List<Product>();
            var sql = _defaultDbContext.Products.OrderBy(t => t.Sort).AsQueryable();
            res = sql.Where(t => t.Status == StatusEnum.YES.Code).ToList();
            var config = new MapperConfiguration(cfg => cfg.CreateMap<Product, ProductVo>());
            var mapper = config.CreateMapper();
            return res.Select(item => mapper.Map<ProductVo>(item)).ToList();
        }
    }
}
